﻿namespace DataDuctus.MongoDb.Serialization.Tests
{
	using System.Linq;

	using DataDuctus.MongoDb.Serialization.Tests.Model;

	using Microsoft.VisualStudio.TestTools.UnitTesting;

	using MongoDB.Bson.Serialization;
	using MongoDB.Bson.Serialization.IdGenerators;

	/// <summary>
	/// Summary description for UnitTest1
	/// </summary>
	[TestClass]
	public class BsonClassMapTests
	{
		#region Properties
		/// <summary>
		///Gets or sets the test context which provides
		///information about and functionality for the current test run.
		///</summary>
		public TestContext TestContext { get; set; }
		#endregion // Properties

		#region Primitives
		[TestMethod]
		public void RegisterPrimitivePropertyClass()
		{
			if (!BsonClassMap.IsClassMapRegistered(typeof(PrimitiveTypesPropertiesClass)))
			{
				new DataContractMapper<PrimitiveTypesPropertiesClass>().Register();
			}

			var clsMap = BsonClassMap.LookupClassMap(typeof(PrimitiveTypesPropertiesClass));

			Assert.AreEqual(true, clsMap.IsFrozen);
			Assert.AreEqual(false, clsMap.IsRootClass);
			Assert.AreEqual(false, clsMap.IsAnonymous);
			Assert.AreEqual(typeof(PrimitiveTypesPropertiesClass), clsMap.ClassType);
			Assert.IsNotNull(clsMap.BaseClassMap); // TODO: Is this really correct - it should have null???
			Assert.AreEqual("PrimitiveTypesPropertiesClass", clsMap.Discriminator);
			Assert.AreEqual(false, clsMap.DiscriminatorIsRequired);
			Assert.AreEqual(false,clsMap.HasRootClass);
			Assert.AreEqual(true,clsMap.IgnoreExtraElements);
			Assert.AreEqual(0, clsMap.KnownTypes.Count());
			Assert.AreEqual(StringObjectIdGenerator.Instance, clsMap.IdMemberMap.IdGenerator);
			Assert.AreEqual("Id", clsMap.IdMemberMap.MemberInfo.Name);
		}

		[TestMethod]
		public void RegisterPrimitiveFieldClass()
		{
			if (!BsonClassMap.IsClassMapRegistered(typeof(PrimitiveTypesFieldsClass)))
			{
				new DataContractMapper<PrimitiveTypesFieldsClass>().Register();
			}

			var clsMap = BsonClassMap.LookupClassMap(typeof(PrimitiveTypesFieldsClass));

			Assert.AreEqual(true, clsMap.IsFrozen);
			Assert.AreEqual(false, clsMap.IsRootClass);
			Assert.AreEqual(false, clsMap.IsAnonymous);
			Assert.AreEqual(typeof(PrimitiveTypesFieldsClass), clsMap.ClassType);
			Assert.IsNotNull(clsMap.BaseClassMap);
			Assert.AreEqual("PrimitiveTypesFieldsClass", clsMap.Discriminator);
			Assert.AreEqual(false, clsMap.DiscriminatorIsRequired);
			Assert.AreEqual(false, clsMap.HasRootClass);
			Assert.AreEqual(true, clsMap.IgnoreExtraElements);
			Assert.AreEqual(0, clsMap.KnownTypes.Count());
			Assert.AreEqual(StringObjectIdGenerator.Instance, clsMap.IdMemberMap.IdGenerator);
			Assert.AreEqual("Id", clsMap.IdMemberMap.MemberInfo.Name);
		}
		#endregion // Primitives

		#region Signle Inheritance
		[TestMethod]
		public void MapSingleInheritanceRegisterRootClass()
		{
			if (!BsonClassMap.IsClassMapRegistered(typeof(OneInheritanceA)))
			{
				var regged =  new DataContractMapper<OneInheritanceA>().Register().ToArray(); // Should register OneInhertianceA, OneInhertianceB

				Assert.AreEqual(2, regged.Length);
				Assert.AreEqual(1, (from item in regged where item.Name == "OneInheritanceA" select item).Count());
				Assert.AreEqual(1, (from item in regged where item.Name == "OneInheritanceB" select item).Count());
			}

			var clsMapA = BsonClassMap.LookupClassMap(typeof(OneInheritanceA)); // Freezes classMap (INFO: remove me - investigation phase)
			var clsMapB = BsonClassMap.LookupClassMap(typeof(OneInheritanceB));

			// A
			Assert.AreEqual(true, clsMapA.IsFrozen);
			Assert.AreEqual(true, clsMapA.IsRootClass);
			Assert.AreEqual(false, clsMapA.IsAnonymous);
			Assert.AreEqual(typeof(OneInheritanceA), clsMapA.ClassType);
			Assert.IsNotNull(clsMapA.BaseClassMap);
			Assert.AreEqual("OneInheritanceA", clsMapA.Discriminator);
			Assert.AreEqual(true, clsMapA.DiscriminatorIsRequired);
			Assert.AreEqual(true, clsMapA.HasRootClass); // TODO: ???
			Assert.AreEqual(true, clsMapA.IgnoreExtraElements);
			Assert.AreEqual(1, clsMapA.KnownTypes.Count());
			Assert.AreEqual(StringObjectIdGenerator.Instance, clsMapA.IdMemberMap.IdGenerator);
			Assert.AreEqual("Id", clsMapA.IdMemberMap.MemberInfo.Name);

			// B
			Assert.AreEqual(true, clsMapB.IsFrozen);
			Assert.AreEqual(false, clsMapB.IsRootClass);
			Assert.AreEqual(false, clsMapB.IsAnonymous);
			Assert.AreEqual(typeof(OneInheritanceB), clsMapB.ClassType);
			Assert.AreEqual(clsMapA, clsMapB.BaseClassMap);
			Assert.AreEqual("OneInheritanceB", clsMapB.Discriminator);
			Assert.AreEqual(true, clsMapB.DiscriminatorIsRequired);
			Assert.AreEqual(true, clsMapB.HasRootClass);
			Assert.AreEqual(true, clsMapB.IgnoreExtraElements);
			Assert.AreEqual(0, clsMapB.KnownTypes.Count());
			Assert.AreEqual(StringObjectIdGenerator.Instance, clsMapA.IdMemberMap.IdGenerator); // From OneInheritanceA
			Assert.AreEqual("Id", clsMapB.IdMemberMap.MemberInfo.Name); // From OneInheritanceA
		}

		[TestMethod]
		public void MapSingleInheritanceRegisterSubclass()
		{
			if (!BsonClassMap.IsClassMapRegistered(typeof(OneInheritanceRegisterSubclassB)))
			{
				// Should register OneInheritanceRegisterSubclassA, OneInheritanceRegisterSubclassB
				var regged = new DataContractMapper<OneInheritanceRegisterSubclassB>().Register().ToArray();

				Assert.AreEqual(2,regged.Length);
				Assert.AreEqual(1,(from item in regged where item.Name == "OneInheritanceRegisterSubclassA" select item).Count());
				Assert.AreEqual(1, (from item in regged where item.Name == "OneInheritanceRegisterSubclassB" select item).Count());
			}

			var clsMapA = BsonClassMap.LookupClassMap(typeof(OneInheritanceRegisterSubclassA));
			var clsMapB = BsonClassMap.LookupClassMap(typeof(OneInheritanceRegisterSubclassB));

			// A
			Assert.AreEqual(true, clsMapA.IsFrozen);
			Assert.AreEqual(true, clsMapA.IsRootClass);
			Assert.AreEqual(false, clsMapA.IsAnonymous);
			Assert.AreEqual(typeof(OneInheritanceRegisterSubclassA), clsMapA.ClassType);
			Assert.IsNotNull(clsMapA.BaseClassMap);
			Assert.AreEqual("OneInheritanceRegisterSubclassA", clsMapA.Discriminator);
			Assert.AreEqual(true, clsMapA.DiscriminatorIsRequired);
			Assert.AreEqual(true, clsMapA.HasRootClass);
			Assert.AreEqual(true, clsMapA.IgnoreExtraElements);
			Assert.AreEqual(1, clsMapA.KnownTypes.Count());
			Assert.AreEqual(StringObjectIdGenerator.Instance, clsMapA.IdMemberMap.IdGenerator);
			Assert.AreEqual("Id", clsMapA.IdMemberMap.MemberInfo.Name);

			// B
			Assert.AreEqual(true, clsMapB.IsFrozen);
			Assert.AreEqual(false, clsMapB.IsRootClass);
			Assert.AreEqual(false, clsMapB.IsAnonymous);
			Assert.AreEqual(typeof(OneInheritanceRegisterSubclassB), clsMapB.ClassType);
			Assert.AreEqual(clsMapA, clsMapB.BaseClassMap);
			Assert.AreEqual("OneInheritanceRegisterSubclassB", clsMapB.Discriminator);
			Assert.AreEqual(true, clsMapB.DiscriminatorIsRequired);
			Assert.AreEqual(true, clsMapB.HasRootClass);
			Assert.AreEqual(true, clsMapB.IgnoreExtraElements);
			Assert.AreEqual(0, clsMapB.KnownTypes.Count());
			Assert.AreEqual(StringObjectIdGenerator.Instance, clsMapA.IdMemberMap.IdGenerator); // From OneInheritanceA
			Assert.AreEqual("Id", clsMapA.IdMemberMap.MemberInfo.Name); // From OneInheritanceA
		}
		#endregion // Signle Inheritance

		#region Single Level Composition
		[TestMethod]
		public void MapSingleLevelComposition()
		{
			if (!BsonClassMap.IsClassMapRegistered(typeof(SingleLevelCompositionMain)))
			{
				var regged = new DataContractMapper<SingleLevelCompositionMain>().Register().ToArray(); // Should register SingleLevelCompositionMain, SingleLevelCompositionComposite

				Assert.AreEqual(2, regged.Length);
				Assert.AreEqual(1, (from item in regged where item.Name == "SingleLevelCompositionMain" select item).Count());
				Assert.AreEqual(1, (from item in regged where item.Name == "SingleLevelCompositionComposite" select item).Count());
			}

			var clsMapMain = BsonClassMap.LookupClassMap(typeof(SingleLevelCompositionMain));
			var clsMapComposite = BsonClassMap.LookupClassMap(typeof(SingleLevelCompositionComposite));

			// Main
			Assert.AreEqual(true, clsMapMain.IsFrozen);
			Assert.AreEqual(false, clsMapMain.IsRootClass);
			Assert.AreEqual(false, clsMapMain.IsAnonymous);
			Assert.AreEqual(typeof(SingleLevelCompositionMain), clsMapMain.ClassType);
			Assert.IsNotNull(clsMapMain.BaseClassMap);
			Assert.AreEqual("SingleLevelCompositionMain", clsMapMain.Discriminator);
			Assert.AreEqual(false, clsMapMain.DiscriminatorIsRequired);
			Assert.AreEqual(false, clsMapMain.HasRootClass);
			Assert.AreEqual(true, clsMapMain.IgnoreExtraElements);
			Assert.AreEqual(0, clsMapMain.KnownTypes.Count());
			Assert.AreEqual(StringObjectIdGenerator.Instance, clsMapMain.IdMemberMap.IdGenerator);
			Assert.AreEqual("Id", clsMapMain.IdMemberMap.MemberInfo.Name);

			// Composite
			Assert.AreEqual(true, clsMapComposite.IsFrozen);
			Assert.AreEqual(false, clsMapComposite.IsRootClass);
			Assert.AreEqual(false, clsMapComposite.IsAnonymous);
			Assert.AreEqual(typeof(SingleLevelCompositionComposite), clsMapComposite.ClassType);
			Assert.IsNotNull(clsMapComposite.BaseClassMap);
			Assert.AreEqual("SingleLevelCompositionComposite", clsMapComposite.Discriminator);
			Assert.AreEqual(false, clsMapComposite.DiscriminatorIsRequired);
			Assert.AreEqual(false, clsMapComposite.HasRootClass);
			Assert.AreEqual(true, clsMapComposite.IgnoreExtraElements);
			Assert.AreEqual(0, clsMapComposite.KnownTypes.Count());
			Assert.AreEqual(null, clsMapComposite.IdMemberMap);
		}
		#endregion // Single Level Composition

		#region Single Level Composition Single Inheritance
		[TestMethod]
		public void MapSingleLevelCompositionSingleInheritance()
		{
			if (!BsonClassMap.IsClassMapRegistered(typeof(SingleLevelCompositionOneInheritanceMain)))
			{
				// Should register SingleLevelCompositionOneInheritanceMain, SingleLevelCompositionOneInheritanceA, SingleLevelCompositionOneInheritanceB
				var regged = new DataContractMapper<SingleLevelCompositionOneInheritanceMain>().Register().ToArray();

				Assert.AreEqual(3, regged.Length);
				Assert.AreEqual(1, (from item in regged where item.Name == "SingleLevelCompositionOneInheritanceMain" select item).Count());
				Assert.AreEqual(1, (from item in regged where item.Name == "SingleLevelCompositionOneInheritanceA" select item).Count());
				Assert.AreEqual(1, (from item in regged where item.Name == "SingleLevelCompositionOneInheritanceB" select item).Count());
			}

			var clsMapMain = BsonClassMap.LookupClassMap(typeof(SingleLevelCompositionOneInheritanceMain));
			var clsMapCompositeA = BsonClassMap.LookupClassMap(typeof(SingleLevelCompositionOneInheritanceA));
			var clsMapCompositeB = BsonClassMap.LookupClassMap(typeof(SingleLevelCompositionOneInheritanceB));

			// Main
			Assert.AreEqual(true, clsMapMain.IsFrozen);
			Assert.AreEqual(false, clsMapMain.IsRootClass);
			Assert.AreEqual(false, clsMapMain.IsAnonymous);
			Assert.AreEqual(typeof(SingleLevelCompositionOneInheritanceMain), clsMapMain.ClassType);
			Assert.IsNotNull(clsMapMain.BaseClassMap);
			Assert.AreEqual("SingleLevelCompositionOneInheritanceMain", clsMapMain.Discriminator);
			Assert.AreEqual(false, clsMapMain.DiscriminatorIsRequired);
			Assert.AreEqual(false, clsMapMain.HasRootClass);
			Assert.AreEqual(true, clsMapMain.IgnoreExtraElements);
			Assert.AreEqual(0, clsMapMain.KnownTypes.Count());
			Assert.AreEqual(StringObjectIdGenerator.Instance, clsMapMain.IdMemberMap.IdGenerator);
			Assert.AreEqual("Id", clsMapMain.IdMemberMap.MemberInfo.Name);

			// Composite A
			Assert.AreEqual(true, clsMapCompositeA.IsFrozen);
			Assert.AreEqual(true, clsMapCompositeA.IsRootClass);
			Assert.AreEqual(false, clsMapCompositeA.IsAnonymous);
			Assert.AreEqual(typeof(SingleLevelCompositionOneInheritanceA), clsMapCompositeA.ClassType);
			Assert.IsNotNull(clsMapCompositeA.BaseClassMap);
			Assert.AreEqual("SingleLevelCompositionOneInheritanceA", clsMapCompositeA.Discriminator);
			Assert.AreEqual(true, clsMapCompositeA.DiscriminatorIsRequired);
			Assert.AreEqual(true, clsMapCompositeA.HasRootClass);
			Assert.AreEqual(true, clsMapCompositeA.IgnoreExtraElements);
			Assert.AreEqual(1, clsMapCompositeA.KnownTypes.Count());
			Assert.AreEqual(StringObjectIdGenerator.Instance, clsMapCompositeA.IdMemberMap.IdGenerator);
			Assert.AreEqual("Id", clsMapCompositeA.IdMemberMap.MemberInfo.Name);

			// Composite B
			Assert.AreEqual(true, clsMapCompositeB.IsFrozen);
			Assert.AreEqual(false, clsMapCompositeB.IsRootClass);
			Assert.AreEqual(false, clsMapCompositeB.IsAnonymous);
			Assert.AreEqual(typeof(SingleLevelCompositionOneInheritanceB), clsMapCompositeB.ClassType);
			Assert.AreEqual(clsMapCompositeA, clsMapCompositeB.BaseClassMap);
			Assert.AreEqual("SingleLevelCompositionOneInheritanceB", clsMapCompositeB.Discriminator);
			Assert.AreEqual(true, clsMapCompositeB.DiscriminatorIsRequired);
			Assert.AreEqual(true, clsMapCompositeB.HasRootClass);
			Assert.AreEqual(true, clsMapCompositeB.IgnoreExtraElements);
			Assert.AreEqual(0, clsMapCompositeB.KnownTypes.Count());
			Assert.AreEqual(StringObjectIdGenerator.Instance, clsMapCompositeB.IdMemberMap.IdGenerator);
			Assert.AreEqual("Id", clsMapCompositeB.IdMemberMap.MemberInfo.Name);
		}
		#endregion // Single Level Composition Single Inheritance

		#region Multi Level Composition
		[TestMethod]
		public void MapMultiLevelComposition()
		{
			if (!BsonClassMap.IsClassMapRegistered(typeof(MulitLevelCompositionMain)))
			{
				// Should register MulitLevelCompositionMain, MulitLevelCompositionCompositeA
				// MulitLevelCompositionCompositeB, MulitLevelCompositionCompositeC, MulitLevelCompositionCompositeD
				var regged = new DataContractMapper<MulitLevelCompositionMain>().Register().ToArray();

				Assert.AreEqual(5, regged.Length);
				Assert.AreEqual(1, (from item in regged where item.Name == "MulitLevelCompositionMain" select item).Count());
				Assert.AreEqual(1, (from item in regged where item.Name == "MulitLevelCompositionCompositeA" select item).Count());
				Assert.AreEqual(1, (from item in regged where item.Name == "MulitLevelCompositionCompositeB" select item).Count());
				Assert.AreEqual(1, (from item in regged where item.Name == "MulitLevelCompositionCompositeC" select item).Count());
				Assert.AreEqual(1, (from item in regged where item.Name == "MulitLevelCompositionCompositeD" select item).Count());
			}

			var clsMapMain = BsonClassMap.LookupClassMap(typeof(MulitLevelCompositionMain));
			var clsMapCompositeA = BsonClassMap.LookupClassMap(typeof(MulitLevelCompositionCompositeA));
			var clsMapCompositeB = BsonClassMap.LookupClassMap(typeof(MulitLevelCompositionCompositeB));
			var clsMapCompositeC = BsonClassMap.LookupClassMap(typeof(MulitLevelCompositionCompositeC));
			var clsMapCompositeD = BsonClassMap.LookupClassMap(typeof(MulitLevelCompositionCompositeD));

			// Main
			Assert.AreEqual(true, clsMapMain.IsFrozen);
			Assert.AreEqual(false, clsMapMain.IsRootClass);
			Assert.AreEqual(false, clsMapMain.IsAnonymous);
			Assert.AreEqual(typeof(MulitLevelCompositionMain), clsMapMain.ClassType);
			Assert.IsNotNull(clsMapMain.BaseClassMap);
			Assert.AreEqual("MulitLevelCompositionMain", clsMapMain.Discriminator);
			Assert.AreEqual(false, clsMapMain.DiscriminatorIsRequired);
			Assert.AreEqual(false, clsMapMain.HasRootClass);
			Assert.AreEqual(true, clsMapMain.IgnoreExtraElements);
			Assert.AreEqual(0, clsMapMain.KnownTypes.Count());
			Assert.AreEqual(StringObjectIdGenerator.Instance, clsMapMain.IdMemberMap.IdGenerator);
			Assert.AreEqual("Id", clsMapMain.IdMemberMap.MemberInfo.Name);

			// Composite A
			Assert.AreEqual(true, clsMapCompositeA.IsFrozen);
			Assert.AreEqual(false, clsMapCompositeA.IsRootClass);
			Assert.AreEqual(false, clsMapCompositeA.IsAnonymous);
			Assert.AreEqual(typeof(MulitLevelCompositionCompositeA), clsMapCompositeA.ClassType);
			Assert.IsNotNull(clsMapCompositeA.BaseClassMap);
			Assert.AreEqual("MulitLevelCompositionCompositeA", clsMapCompositeA.Discriminator);
			Assert.AreEqual(false, clsMapCompositeA.DiscriminatorIsRequired);
			Assert.AreEqual(false, clsMapCompositeA.HasRootClass);
			Assert.AreEqual(true, clsMapCompositeA.IgnoreExtraElements);
			Assert.AreEqual(0, clsMapCompositeA.KnownTypes.Count());
			Assert.AreEqual(null, clsMapCompositeA.IdMemberMap);

			// Composite B
			Assert.AreEqual(true, clsMapCompositeB.IsFrozen);
			Assert.AreEqual(false, clsMapCompositeB.IsRootClass);
			Assert.AreEqual(false, clsMapCompositeB.IsAnonymous);
			Assert.AreEqual(typeof(MulitLevelCompositionCompositeB), clsMapCompositeB.ClassType);
			Assert.IsNotNull(clsMapCompositeB.BaseClassMap);
			Assert.AreEqual("MulitLevelCompositionCompositeB", clsMapCompositeB.Discriminator);
			Assert.AreEqual(false, clsMapCompositeB.DiscriminatorIsRequired);
			Assert.AreEqual(false, clsMapCompositeB.HasRootClass);
			Assert.AreEqual(true, clsMapCompositeB.IgnoreExtraElements);
			Assert.AreEqual(0, clsMapCompositeB.KnownTypes.Count());
			Assert.AreEqual(null, clsMapCompositeB.IdMemberMap);

			// Composite C
			Assert.AreEqual(true, clsMapCompositeC.IsFrozen);
			Assert.AreEqual(false, clsMapCompositeC.IsRootClass);
			Assert.AreEqual(false, clsMapCompositeC.IsAnonymous);
			Assert.AreEqual(typeof(MulitLevelCompositionCompositeC), clsMapCompositeC.ClassType);
			Assert.IsNotNull(clsMapCompositeC.BaseClassMap);
			Assert.AreEqual("MulitLevelCompositionCompositeC", clsMapCompositeC.Discriminator);
			Assert.AreEqual(false, clsMapCompositeC.DiscriminatorIsRequired);
			Assert.AreEqual(false, clsMapCompositeC.HasRootClass);
			Assert.AreEqual(true, clsMapCompositeC.IgnoreExtraElements);
			Assert.AreEqual(0, clsMapCompositeC.KnownTypes.Count());
			Assert.AreEqual(null, clsMapCompositeC.IdMemberMap);

			// Composite D
			Assert.AreEqual(true, clsMapCompositeD.IsFrozen);
			Assert.AreEqual(false, clsMapCompositeD.IsRootClass);
			Assert.AreEqual(false, clsMapCompositeD.IsAnonymous);
			Assert.AreEqual(typeof(MulitLevelCompositionCompositeD), clsMapCompositeD.ClassType);
			Assert.IsNotNull(clsMapCompositeD.BaseClassMap);
			Assert.AreEqual("MulitLevelCompositionCompositeD", clsMapCompositeD.Discriminator);
			Assert.AreEqual(false, clsMapCompositeD.DiscriminatorIsRequired);
			Assert.AreEqual(false, clsMapCompositeD.HasRootClass);
			Assert.AreEqual(true, clsMapCompositeD.IgnoreExtraElements);
			Assert.AreEqual(0, clsMapCompositeD.KnownTypes.Count());
			Assert.AreEqual(null, clsMapCompositeD.IdMemberMap);
		}
		#endregion // Multi Level Composition

		#region KnownType for non inherited class gets misinterpreted (Issiue#764)
		[TestMethod]
		public void Issiue764()
		{
			if (!BsonClassMap.IsClassMapRegistered(typeof(TypeContainingAnKnownTypeOfUndeterminablePropertyType)))
			{
				// Should register TypeContainingAnKnownTypeOfUndeterminablePropertyType, TypeThatResidesInUnterminablePropertyType
				// where TypeThatResidesInUnterminablePropertyType should be registered as a "regular" classmap not a known type to
				// TypeContainingAnKnownTypeOfUndeterminablePropertyType.
				var regged = new DataContractMapper<TypeContainingAnKnownTypeOfUndeterminablePropertyType>().Register().ToArray();

				Assert.AreEqual(2, regged.Length);
				Assert.AreEqual(1, (from item in regged where item.Name == "TypeContainingAnKnownTypeOfUndeterminablePropertyType" select item).Count());
				Assert.AreEqual(1, (from item in regged where item.Name == "TypeThatResidesInUnterminablePropertyType" select item).Count());
			}

			var clsMapObj = BsonClassMap.LookupClassMap(typeof(object));
			var clsMapA = BsonClassMap.LookupClassMap(typeof(TypeContainingAnKnownTypeOfUndeterminablePropertyType));
			var clsMapB = BsonClassMap.LookupClassMap(typeof(TypeThatResidesInUnterminablePropertyType));

			// A
			Assert.AreEqual(true, clsMapA.IsFrozen);
			Assert.AreEqual(false, clsMapA.IsRootClass);
			Assert.AreEqual(false, clsMapA.IsAnonymous);
			Assert.AreEqual(typeof(TypeContainingAnKnownTypeOfUndeterminablePropertyType), clsMapA.ClassType);
			Assert.AreEqual(clsMapObj, clsMapA.BaseClassMap);
			Assert.AreEqual("TypeContainingAnKnownTypeOfUndeterminablePropertyType", clsMapA.Discriminator);
			Assert.AreEqual(false, clsMapA.DiscriminatorIsRequired);
			Assert.AreEqual(false, clsMapA.HasRootClass);
			Assert.AreEqual(true, clsMapA.IgnoreExtraElements);
			Assert.AreEqual(0, clsMapA.KnownTypes.Count());
			Assert.AreEqual(StringObjectIdGenerator.Instance, clsMapA.IdMemberMap.IdGenerator);
			Assert.AreEqual("Id", clsMapA.IdMemberMap.MemberInfo.Name);
			Assert.AreEqual(2, clsMapA.DeclaredMemberMaps.Count()); // Id, DataContractMappedType

			// B
			Assert.AreEqual(true, clsMapB.IsFrozen);
			Assert.AreEqual(false, clsMapB.IsRootClass);
			Assert.AreEqual(false, clsMapB.IsAnonymous);
			Assert.AreEqual(typeof(TypeThatResidesInUnterminablePropertyType), clsMapB.ClassType);
			Assert.AreEqual(clsMapObj, clsMapB.BaseClassMap);
			Assert.AreEqual("TypeThatResidesInUnterminablePropertyType", clsMapB.Discriminator);
			Assert.AreEqual(false, clsMapB.DiscriminatorIsRequired);
			Assert.AreEqual(false, clsMapB.HasRootClass);
			Assert.AreEqual(true, clsMapB.IgnoreExtraElements);
			Assert.AreEqual(0, clsMapB.KnownTypes.Count());
			Assert.AreEqual(null, clsMapB.IdMemberMap);
      Assert.AreEqual(1, clsMapB.DeclaredMemberMaps.Count()); // HelloWorldProperty
		}
		#endregion // KnownType for non inherited class gets misinterpreted (Issiue#764)

		#region Bastype Abstract Property Subclass With Decorated Override (Issiue#766)
		[TestMethod]
		public void Issiue766()
		{
			if (!BsonClassMap.IsClassMapRegistered(typeof(BaseTypeAbstractProperty)))
			{
				var regged = new DataContractMapper<BaseTypeAbstractProperty>().Register().ToArray(); // Should register BaseTypeAbstractProperty, SubclassDecoratedOverride

				Assert.AreEqual(2, regged.Length);
				Assert.AreEqual(1, (from item in regged where item.Name == "BaseTypeAbstractProperty" select item).Count());
				Assert.AreEqual(1, (from item in regged where item.Name == "SubclassDecoratedOverride" select item).Count());
			}

			var clsMapA = BsonClassMap.LookupClassMap(typeof(BaseTypeAbstractProperty));
			var clsMapB = BsonClassMap.LookupClassMap(typeof(SubclassDecoratedOverride));

			// A
			Assert.AreEqual(true, clsMapA.IsFrozen);
			Assert.AreEqual(true, clsMapA.IsRootClass);
			Assert.AreEqual(false, clsMapA.IsAnonymous);
			Assert.AreEqual(typeof(BaseTypeAbstractProperty), clsMapA.ClassType);
			Assert.IsNotNull(clsMapA.BaseClassMap);
			Assert.AreEqual("BaseTypeAbstractProperty", clsMapA.Discriminator);
			Assert.AreEqual(true, clsMapA.DiscriminatorIsRequired);
			Assert.AreEqual(true, clsMapA.HasRootClass); // TODO: ???
			Assert.AreEqual(true, clsMapA.IgnoreExtraElements);
			Assert.AreEqual(1, clsMapA.KnownTypes.Count());
			Assert.AreEqual(StringObjectIdGenerator.Instance, clsMapA.IdMemberMap.IdGenerator);
			Assert.AreEqual("Id", clsMapA.IdMemberMap.MemberInfo.Name);

			// B
			Assert.AreEqual(true, clsMapB.IsFrozen);
			Assert.AreEqual(false, clsMapB.IsRootClass);
			Assert.AreEqual(false, clsMapB.IsAnonymous);
			Assert.AreEqual(typeof(SubclassDecoratedOverride), clsMapB.ClassType);
			Assert.AreEqual(clsMapA, clsMapB.BaseClassMap);
			Assert.AreEqual("SubclassDecoratedOverride", clsMapB.Discriminator);
			Assert.AreEqual(true, clsMapB.DiscriminatorIsRequired);
			Assert.AreEqual(true, clsMapB.HasRootClass);
			Assert.AreEqual(true, clsMapB.IgnoreExtraElements);
			Assert.AreEqual(0, clsMapB.KnownTypes.Count());
			Assert.AreEqual(StringObjectIdGenerator.Instance, clsMapB.IdMemberMap.IdGenerator);
			Assert.AreEqual("Id", clsMapB.IdMemberMap.MemberInfo.Name);			
		}
		#endregion Bastype Abstract Property Subclass With Decorated Override (Issiue#766)
	}
}
